package com.mallcloud.mall.app.service.impl;

import cn.hutool.core.map.MapBuilder;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.mallcloud.mall.admin.api.entity.SysSocialDetails;
import com.mallcloud.mall.admin.mapper.SysSocialDetailsMapper;
import com.mallcloud.mall.app.api.constant.ApiConstants;
import com.mallcloud.mall.app.api.entity.vo.WxApiAccessTokenVO;
import com.mallcloud.mall.app.api.entity.vo.WxApiJsCodeToSessionVO;
import com.mallcloud.mall.app.api.entity.vo.WxApiPhoneNumberVO;
import com.mallcloud.mall.app.config.WechatConfig;
import com.mallcloud.mall.app.service.AppWxApiService;
import com.mallcloud.mall.common.core.constant.enums.LoginTypeEnum;
import com.mallcloud.mall.common.core.exception.FailException;
import com.mallcloud.mall.common.core.util.HttpUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Objects;

@Slf4j
@Service
@RequiredArgsConstructor
@ConditionalOnProperty("const.wxapp.appId")
public class AppWxApiServiceImpl implements AppWxApiService {

    private final WechatConfig wechatConfig;
    private final HttpUtil httpUtil;
    private final SysSocialDetailsMapper sysSocialDetailsMapper;

    @Override
    public String getUserPhoneNumber(String code) {
        JSONObject requestBody = new JSONObject();
        requestBody.put("code", code);

        WxApiPhoneNumberVO phoneNumber = httpUtil.exchange(
                ApiConstants.WxApi.getUserPhoneNumber.getUrl(),
                ApiConstants.WxApi.getUserPhoneNumber.getMethod(),
                MapBuilder.create(new HashMap<String, String>())
                        .put(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                        .build(),
                MapBuilder.create(new HashMap<String, Object>())
                        .put("access_token", this.getAccessToken())
                        .build(),
                requestBody,
                ApiConstants.WxApi.getUserPhoneNumber.getResponseClass()
        );
        if (!phoneNumber.isSuccess()) {
            log.error(JSON.toJSONString(phoneNumber));
            throw new FailException("获取手机号失败：" + phoneNumber.getErrCodeDesc());
        }
        return phoneNumber.getPhoneInfo().getPhoneNumber();
    }

    @Override
    public String getAccessToken() {
        WxApiAccessTokenVO accessToken = httpUtil.exchange(
                ApiConstants.WxApi.getAccessToken.getUrl(),
                ApiConstants.WxApi.getAccessToken.getMethod(),
                null,
                MapBuilder.create(new HashMap<String, Object>())
                        .put("grant_type", "client_credential")
                        .put("appid", wechatConfig.getAppId())
                        .put("secret", wechatConfig.getAppSecret())
                        .build(),
                null,
                ApiConstants.WxApi.getAccessToken.getResponseClass()
        );
        if (!accessToken.isSuccess()) {
            log.error(JSON.toJSONString(accessToken));
            throw new FailException("获取接口调用凭据失败：" + accessToken.getErrCodeDesc());
        }
        return accessToken.getAccessToken();
    }

    @Override
    public String jsCodeToSession(String code) {
        SysSocialDetails condition = new SysSocialDetails();
        condition.setType(LoginTypeEnum.MINI_APP.getType());
        SysSocialDetails socialDetails = sysSocialDetailsMapper.selectOne(new QueryWrapper<>(condition));
        if(Objects.isNull(socialDetails)){
            throw new FailException("小程序信息未配置");
        }

        WxApiJsCodeToSessionVO codeToSession = httpUtil.exchange(
                ApiConstants.WxApi.jsCode2session.getUrl(),
                ApiConstants.WxApi.jsCode2session.getMethod(),
                null,
                MapBuilder.create(new HashMap<String, Object>())
                        .put("appid", socialDetails.getAppId())
                        .put("secret", socialDetails.getAppSecret())
                        .put("js_code", code)
                        .put("grant_type", "authorization_code")
                        .build(),
                null,
                ApiConstants.WxApi.jsCode2session.getResponseClass()
        );
        if (!codeToSession.isSuccess()) {
            log.error(JSON.toJSONString(codeToSession));
            throw new FailException("小程序登录失败：" + codeToSession.getErrCodeDesc());
        }
        return codeToSession.getOpenId();
    }
}